<?php
/**
 *
 * Author: TheSmile
 * Date: 2023/7/20 16:42
 * Email: <594652523@qq.com>
 */

namespace App\Http\Services;

use App\Exceptions\ServiceException;
use App\Exceptions\ServiceExceptionConstant;
use App\Http\Repositories\Daos\Order\OrderDao;
use App\Http\Repositories\Daos\Trade\TradeDao;
use App\Http\Repositories\Daos\Trade\TradeLogDao;
use App\Models\DragDetail;
use App\Models\RefundOrder;
use App\Util\WechatPay\WechatPayUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TradeNotifyService
{
    protected $tradeDao;
    protected $tradeLogDao;
    protected $orderDao;

    public function __construct(TradeDao $tradeDao, TradeLogDao $tradeLogDao, OrderDao $orderDao)
    {
        $this->tradeDao    = $tradeDao;
        $this->tradeLogDao = $tradeLogDao;
        $this->orderDao    = $orderDao;
    }

    public function wechatNotify()
    {

        $rel = (new WechatPayUtil())->checkNotifySign();
        if ($rel === false) {
            return response()->json(['code' => 'FAIL', 'message' => '签名验证失败'], 500);
        }
        Log::info('回调数据集:', $rel);
        $wechatConfig = config('wechat.payment.default');
        //1判断是自己商户
        if ($wechatConfig['mch_id'] != $rel['mchid'] || $wechatConfig['app_id'] != $rel['appid']) {
            Log::error('微信支付回调异常，订单：' . $rel['out_trade_no']);
            return response()->json(['code' => 'FAIL', 'message' => 'mchid或appid异常']);
        }
        //2判断支付状态
        if ($rel['trade_state'] != 'SUCCESS') {
            //交易失败，告知微信通知成功且我方不做任何操作
            return response()->json(['code' => 'SUCCESS', 'message' => '']);
        }

        $res = $this->setTradeSuccess($rel);
        if ($res) {
            return response()->json(['code' => 'SUCCESS', 'message' => '']);
        }
        return response()->json(['code' => 'FAIL', 'message' => '参数异常'], 500);
    }

    public function setTradeSuccess($receiveData)
    {
        $trade = $this->tradeDao->getOne(['order_sn' => $receiveData['out_trade_no']]);
        if ($trade['state'] == 1) {//已支付
            return true;
        }
        $data['trade_id']  = $trade['id'];
        $data['response']  = json_encode($receiveData);
        $data['error_log'] = $receiveData['trade_state_desc'];
        $flag              = false;
        //非测试支付判断微信支付回调的金额是否和trade表一致
        if (!config('wechat.payment.default.pay_test') && $trade['amount_pay'] != $receiveData['amount']['payer_total']) {
            $data['error_log'] = '支付金额异常,需付：' . $trade['amount_pay'] . '实际支付:' . $receiveData['amount']['payer_total'];
            $flag              = true;
        }
        $this->tradeLogDao->save($data);
        if ($flag) {
            Log::info('交易号' . $receiveData['out_trade_no'] . '金额异常.订单状态暂未更新');
            return true;
        }
        DB::beginTransaction();
        try {
            //更新交易状态
            $trade->state           = 1;
            $trade->paid_at         = time();
            $trade->trade_sn_return = $receiveData['transaction_id'];
            $trade->save();
            switch ($trade['trade_type']) {
                case 'shop_order':
                    $this->setShopOrderIsPay($trade['order_ids']);
                    break;
                default:
                    break;
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('支付回调更新状态失败,订单号：' . $trade['order_ids'] . ',错误：' . $e->getMessage() . ',文件：' . $e->getFile() . ',行：' . $e->getLine());
            return false;
        }
    }

    public function setShopOrderIsPay($orderId)
    {
        $order                = $this->orderDao->getOne(['id' => $orderId]);
        $order->pay_status    = 1;
        $order->pay_at        = time();
        $max                  = $this->orderDao->getModel()->where('dragon_id', $order['dragon_id'])->max('dragon_serial');
        $order->dragon_serial = $max + 1;
        $order->save();
    }

    public function wechatRefundNotify()
    {
        $rel = (new WechatPayUtil())->checkNotifySign();
        Log::info('微信退款回调数据集:', $rel);
        if ($rel === false) {
            return response()->json(['code' => 'FAIL', 'message' => '签名验证失败'], 500);
        }
        $refundOrder = RefundOrder::where('th_order_sn', $rel['out_refund_no'])->first();
        if (!empty($refundOrder) && $refundOrder['status'] != 1) {
            Log::info('退款订单：' . $refundOrder['id'] . '退款异常-1');
            return response()->json(['code' => 'SUCCESS', 'message' => '']);//本方信息异常但告知微信成功
        }

        DB::beginTransaction();
        try {
            $status                      = $rel['refund_status'] == 'SUCCESS' ? 2 : 3;
            $refundOrder->status         = $status;
            $refundOrder->transaction_id = $rel['transaction_id'];
            $refundOrder->refund_id      = $rel['refund_id'];
            $refundOrder->fail_reason    = $status == 3 ? $rel['refund_status'] : '';//SUCCESS：退款成功CLOSED：退款关闭ABNORMAL：退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往【商户平台—>交易中心】，手动处理此笔退款,示例值：SUCCESS
            if ($status == 2) {
                $refundOrder->refund_at = time();
            }
            $refundOrder->save();
            $orderInfo = $this->orderDao->getOne(['id' => $refundOrder['order_id']]);
            //处理库存
            if ($status == 2) {
                foreach ($orderInfo['goods_snap'] as $item) {
                    $res = DragDetail::where('id', $item['id'])->increment('store', $item['num']);
                    if (!$res) {
                        throw new ServiceException(ServiceExceptionConstant::getErrorData('退款回调库存操作失败'));
                    }
                }
            }
            $orderInfo->status        = -1;
            $orderInfo->refund_status = $status;
            $orderInfo->save();
            DB::commit();
            return response()->json(['code' => 'SUCCESS', 'message' => '']);
        } catch (\Exception $e) {
            Log::error('微信退款回调失败' . $e->getMessage() . '，行:' . $e->getLine() . ',File:' . $e->getFile());
            DB::rollBack();
            return response()->json(['code' => 'FAIL', 'message' => '退款异常-2']);
        }

    }

}
